#!/bin/perl -w

# yang.jin@ebay.com 
#
# $Header: /opt/unixmon/tools/DNS/RCS/named_process_3pp_zones.pl,v 1.215 2016/02/02 09:26:08 yang Exp $

use strict;

# -----------------------------------
# beginning of MAIN 

# my $ROOT	= "/MINE";		# for development/testing
use constant ROOT => "";			# for producttion!!!	

# QA DNS SERVERS:
# dns.qa.ebay.com	10.108.139.154; VIP on Load Blancer 
# qa-dns04.qa.ebay.com	10.109.104.20
# qa-dns05.qa.ebay.com	10.109.104.21
# qa-dns07.qa.ebay.com	10.109.107.73


# use constant ITMASTERS => "10.112.155.231/10.112.155.232"; 
# use constant QAMASTERS => "10.17.70.68/10.17.70.69"; 

use constant QAMASTERS => "10.108.139.154/10.109.107.73"; 
use constant CDMASTERS => "10.14.224.116/10.89.65.39"; 
# use constant MPMASTERS => "10.6.166.15/10.14.166.115"; 
use constant MPMASTERS => "10.43.194.11/10.43.192.10"; 

my $CONF_DIR	= ROOT . "/etc/named"; 
my $TMP_DIR	= ROOT . "/var/named/tmp"; 
my $EXCLUDED;


if ( @ARGV == 2 ) {

	my ($class, $zoneconfig) = @ARGV;
	$class =~ s/\-//; 

	if ( $class eq "mp" || $class eq "qa" || $class eq "mm" ) { 
#		$EXCLUDED = $CONF_DIR . "/excluded/" . $class . ".zones";
		$EXCLUDED = $TMP_DIR . "/allzones-" . $class; 
		read_configs("$class", $zoneconfig); 
		exit 0;
	}
}

printf STDERR "\nThe tool is to convert DNS configuration for zones from other parties into the format required by ITS UNIX.\n";
printf STDERR "\nUsage:\n\t%s -mp|-qa zone-configuration-file\n", $0;
printf STDERR "\n\t\tmp - process configuration of zones from MarketPlace OPS";
printf STDERR "\n\t\tqa - process configuration of zones from MarketPlace QA\n\n";

exit 1;

# end of MAIN
# -----------------------------------


# -----------------------------------
# analyze zones and output the results
# supported zone types: hint master slave foward stub

sub read_configs {

my $zone;
my $type;
my $masters;
my $file;
my $pip;
my @pips;
my @mservers;

my ($class, $zonecfg) = @_;


my @excluded = ();

  if ( -f $EXCLUDED ) {
	@excluded = get_lines($EXCLUDED);
  }

  my @lines = get_lines("$zonecfg");


  my $zonestatement= "";

  foreach (@lines) {
	chomp;
	$_ =~ s/(\/\/|#).*//;   # remove the notes
	$_ =~ s/\/\*.*\*\///;	# remove the notes
	$_ =~ s/\s+/ /g;

 	$_ =~ s/ *allow\-transfer \{(.*)\} *\;//;
 	$_ =~ s/ *allow\-update \{(.*)\} *\;//;
 	$_ =~ s/ *allow\-query \{(.*)\} *\;//;
 	$_ =~ s/ *allow\-notify \{(.*)\} *\;//;
	$_ =~ s/ *notify [\d\.\w]+ *\;//;
 	$_ =~ s/ *also\-notify \{(.*)\} *\;//;
 	$_ =~ s/\s*forward\s+.*\;//;

	$_ =~ s/\" in \{/\" \{/i;  # remove "in" followig the zone name

	if ( /^\s+$/ ) { $_ = ""; next; }
	
	if ( /^\s*zone\s/ ) {
 		if ( $zonestatement ) 
		{ printf STDERR "\nThe following zone on $zonecfg cannot be analayzed:\n$zonestatement\n\n"; $zonestatement = $_; }
		else { $zonestatement = "$zonestatement" . "$_"; }
	} 
	else {
		if ( $zonestatement ) { $zonestatement = "$zonestatement" . "$_"; }
		else  { next; }
	}
	
	$_ = $zonestatement; 

	if ( / *zone \"(.*)\" \{ *type slave *\; *masters \{(.*)\} *\; *file \"(.*)\"\ *; *\} *\;/ ) {
		$type = "slave";
		$zone = $1;
		$masters = $2;
		$file = $3;

		$_ = $zone;
		$zone =~ s/\.$//;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters =~ s/\s+//g;
		$masters =~ s/\;$//;
		$masters =~ s/\;/\//g;

		if ( $class eq "mp" ) { $masters = MPMASTERS; }
		if ( $class eq "qa" ) { 
			$_ = $zone; 
			if ( /^fp[\d\w]+\.qa\.ebay\.com$/ ) { 
				$masters = CDMASTERS; 
			}
			else {
				$masters = QAMASTERS; 
			}
		} 
		
		@mservers = split("/", $masters);

		$_ = $zone;
		if ( /\.in\-addr\.arpa$/ ) { 
			$pip = $_;
			$pip =~ s/\.in\-addr\.arpa$//;
			$pip = join(".", reverse split(/\./, $pip));
			$file = "named.rev-" . $pip;
		}
		else { $file = "db." . $zone; }
		$file = $class . "/" . $file; 
		
		print_slave($zone, $type, $file, @mservers);

		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type slave *\; *file \"(.*)\" *\; *masters \{(.*)\} *\; *\} *\;/ ) { 
		$type = "slave";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = $3;
		$file = $2;
		$masters =~ s/\s+//g;
		$masters =~ s/\;$//;
		$masters =~ s/\;/\//g;
		

	 	# if ( $masters eq "10.6.166.15" ) { $masters = MPMASTERS; }
		if ( $class eq "mp" ) { $masters = MPMASTERS; } 
		if ( $class eq "qa" ) { 
			$_ = $zone; 
			if ( /^fp[\d\w]+\.qa\.ebay\.com$/ ) { 
				$masters = CDMASTERS; 
			}
			else {
				$masters = QAMASTERS; 
			}
		} 


		@mservers = split("/", $masters);

		$_ = $zone;
		if ( /\.in\-addr\.arpa$/ ) { 
			$pip = $_;
			$pip =~ s/\.in\-addr\.arpa$//;
			$pip = join(".", reverse split(/\./, $pip));
			$file = "named.rev-" . $pip;
		}
		else { $file = "db." . $zone; }

		$file = $class . "/" . $file; 
		print_slave($zone, $type, $file, @mservers);

		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type stub *\; *masters \{(.*)\} *\; *file \"(.*)\" *\; *\} *\;/ ) {
		$type = "stub";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = $2;
		$file = $3;
		$masters =~ s/\s+//g;
		$masters =~ s/\;$//;
		$masters =~ s/\;/\//g;
		
	 	if ( $masters eq "10.6.166.15" ) { $masters = MPMASTERS; }

		@mservers = split("/", $masters);

		$_ = $zone;
		if ( /\.in\-addr\.arpa$/ ) { 
			$pip = $_;
			$pip =~ s/\.in\-addr\.arpa$//;
			$pip = join(".", reverse split(/\./, $pip));
			$file = "named.rev-" . $pip;
		}
		else { $file = "db." . $zone; }
		
		$file = $class . "/" . $file; 
		print_slave($zone, $type, $file, @mservers);

		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type stub *\; *file \"(.*)\" *\; *masters \{(.*)\} *\; *\} *\;/ ) { 
		$type = "stub";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = $3;
		$file = $2;
		$masters =~ s/\s+//g;
		$masters =~ s/\;$//;
		$masters =~ s/\;/\//g;
		
	 	if ( $masters eq "10.6.166.15" ) { $masters = MPMASTERS; }

		@mservers = split("/", $masters);

		$_ = $zone;
		if ( /\.in\-addr\.arpa$/ ) { 
			$pip = $_;
			$pip =~ s/\.in\-addr\.arpa$//;
			$pip = join(".", reverse split(/\./, $pip));
			$file = "named.rev-" . $pip;
		}
		else { $file = "db." . $zone; }

		$file = $class . "/" . $file; 
		print_slave($zone, $type, $file, @mservers);

		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type forward *\; *forwarders \{(.*)\} *\; *\} *\;/ ) {
		$type = "forward";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = $2;
		$file = "\-";
		$masters =~ s/\s+//g;
		$masters =~ s/\;$//;
		$masters =~ s/\;/\//g;

		# append the 2nd master for MarketPlace zones
	 	if ( $masters eq "10.6.166.15" ) { $masters = MPMASTERS; }

		@mservers = split("/", $masters);

		###### print_forward($zone, $type, @mservers);
		printf STDERR "Warning: forward zone \"%s\" is discarded.\n", $zone;

		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type hint *\; *file \"(.*)\" *\; *\} *\;/ ) {
		$type = "hint";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = "localhost";
		$file = $2;

		# $file = $class . "/" . $file; 
		print_master($zone, $type, $file); 
		$_ = $zonestatement = "";
	}
	elsif ( / *zone \"(.*)\" \{ *type master *\; *file \"(.*)\" *\; *\} *\;/ ) {

		
		$type = "master";
		$zone = $1;

		if ( is_excluded($zone, @excluded) ) { 
			printf STDERR "Warning: zone \"%s\" is defined on %s, skipped.\n", $zone, $EXCLUDED;
			$_ = $zonestatement = ""; 
			next;
		}

		$masters = "localhost";
		$file = $2;

		# convert QA zones, which are master zones on QA master DNS servers, into slave zones.
		if ( $class eq "qa" ) {
		   $type = "slave"; 
			$_ = $zone; 
			if ( /^fp[\d\w]+\.qa\.ebay\.com$/ ) { 
				$masters = CDMASTERS; 
			}
			else {
				$masters = QAMASTERS; 
			}
		   @mservers = split("/", $masters);
		   $_ = $zone;
		   if ( /\.in\-addr\.arpa$/ ) { 
			$pip = $_;
			$pip =~ s/\.in\-addr\.arpa$//;
			$pip = join(".", reverse split(/\./, $pip));
			$file = "named.rev-" . $pip;
		   }
		   else { $file = "db." . $zone; }

		   $file = $class . "/" . $file; 
		   print_slave($zone, $type, $file, @mservers);
		}
		else { print_master($zone, $type, $file); }

		$_ = $zonestatement = "";

	}
	else { 
		next;
	}

  }  # end of foreach (@lines)


}  # end of read_configs 

# -----------------------------------
sub get_lines {
	my ($file) = @_;
	my @data = ();

	open(FILE,"< $file") || die "\nFaild to open file \"$file\", exited.\n";
	@data = <FILE>;
	close(FILE);
	return @data;
}

# -----------------------------------
sub is_excluded {

my ($zone, @excluded) = @_;

  $_=$zone;
  if (/paypal/i ) { return 1; }

  foreach (@excluded) {
	chomp;		
	$_ =~ s/\s+//g;
	# if (/^$zone$/i ) { return 1; }
	if (lc($_) eq lc($zone)) { return 1; }
  } 
  return 0;
}

# -----------------------------------
sub print_master {

my ($zone, $type, $file) = @_; 

  printf STDOUT "zone \"%s\" \{\n", $zone;
  printf STDOUT "\ttype %s\;\n", $type;
  printf STDOUT "\tfile \"%s\"\;\n\}\;\n\n", $file;

}
# -----------------------------------
sub print_slave {

my ($zone, $type, $file, @masters) = @_; 

  printf STDOUT "zone \"%s\" \{\n", $zone;
  printf STDOUT "\ttype %s\;\n", $type;
  printf STDOUT "\tmasters \{ ";

  foreach (@masters) {
	printf STDOUT "%s\; ", $_;
  }

  printf STDOUT "\}\;\n";
  printf STDOUT "\tfile \"%s\"\;\n\}\;\n\n", $file;

}
# -----------------------------------
sub print_forward {

my ($zone, $type, @fowarders) = @_; 

  printf STDOUT "zone \"%s\" \{\n", $zone;
  printf STDOUT "\ttype %s\;\n", $type;
  printf STDOUT "\tforwarders \{ ";

  foreach (@fowarders) {
	printf STDOUT "%s\; ", $_;
  }

  printf  STDOUT "\}\;\n\}\;\n\n";

}
# -----------------------------------
